home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 2.iso / dist / fw_glimpse.idb / usr / freeware / src / glimpse-3.0 / agrep / preprocess.c.z / preprocess.c
C/C++ Source or Header  |  1997-09-09  |  9KB  |  349 lines

  1. /* Copyright (c) 1994 Sun Wu, Udi Manber, Burra Gopal.  All Rights Reserved. */
  2. /* substitute metachar with special symbol                               */
  3. /* if regularr expression, then set flag REGEX                           */
  4. /* if REGEX and MULTIPAT then report error message,                      */
  5. /* -w only for single word pattern. If WORDBOUND & MULTIWORD error       */
  6. /* process start of line, endof line symbol,                             */
  7. /* process -w WORDBOUND option, append special symbol at begin&end of    */
  8. /* process -d option before this routine                                 */
  9. /* the delimiter pattern is in D_pattern (need to end with '; ')         */
  10. /* if '-t' (suggestion: how about -B) the pattern is passed to sgrep     */
  11. /* and doesn't go here                                                   */
  12. /* in that case, -d is ignored? or not necessary                         */
  13. /* upon return, Pattern contains the pattern to be processed by maskgen  */
  14. /* D_pattern contains transformed D_pattern                              */
  15.  
  16. #include "agrep.h"
  17.  
  18. extern int PAT_FILE, PAT_BUFFER;
  19. extern ParseTree *AParse;
  20. extern int WHOLELINE, REGEX, FASTREGEX, RE_ERR, DELIMITER, TAIL, WORDBOUND;
  21. extern int HEAD;
  22. extern CHAR Progname[];
  23. extern int D_length, tc_D_length;
  24. extern CHAR tc_D_pattern[MaxDelimit * 2];
  25. extern int table[WORD][WORD];
  26. extern int agrep_initialfd;
  27. extern int EXITONERROR;
  28. extern int errno;
  29.  
  30. extern int  multifd;
  31. extern char *multibuf;
  32. extern int  multilen;
  33. extern int anum_terminals;
  34. extern ParseTree aterminals[MAXNUM_PAT];
  35. extern char FREQ_FILE[MAX_LINE_LEN], HASH_FILE[MAX_LINE_LEN], STRING_FILE[MAX_LINE_LEN];    /* interfacing with tcompress */
  36. extern int AComplexBoolean;
  37.  
  38. int
  39. preprocess(D_pattern, Pattern)   /* need two parameters  */
  40. CHAR D_pattern[], Pattern[];
  41. {
  42.     CHAR temp[Maxline], *r_pat, *old_pat;  /* r_pat for r.e. */
  43.     CHAR old_D_pat[MaxDelimit*2];
  44.     int i, j=0, rp=0, m, t=0, num_pos, ANDON = 0;
  45.     int d_end ;  
  46.     int IN_RANGE=0;
  47.     int ret1, ret2;
  48.  
  49. #if    DEBUG
  50.     fprintf(stderr, "preprocess: m=%d, pat=%s, PAT_FILE=%d, PAT_BUFFER=%d\n", strlen(Pattern), Pattern, PAT_FILE, PAT_BUFFER);
  51. #endif
  52.     if ((m = strlen(Pattern)) <= 0) return 0;
  53.     if (PAT_FILE || PAT_BUFFER) return 0;
  54.     REGEX = OFF;
  55.     FASTREGEX = OFF;
  56.     old_pat = Pattern; /* to remember the starting position */
  57.  
  58.     /* Check if pattern is a concatenation of ands OR ors of simple patterns */
  59.     multibuf = (char *)malloc(m * 2 + 2);    /* worst case: a,a,a,a,a,a */
  60.     if (multibuf == NULL) goto normal_processing;
  61.     /* if (WORDBOUND) goto normal_processing; */
  62.  
  63.     multilen = 0;
  64.     AParse = 0;
  65.     ret1 = ret2 = 0;
  66.     if (((ret1 = asplit_pattern(Pattern, m, aterminals, &anum_terminals, &AParse)) <= 0) ||    /* can change the pattern if simple boolean with {} */
  67.         ((ret2 = asplit_terminal(0, anum_terminals, multibuf, &multilen)) <= 0) ||
  68.         ((ret2 == 1) && !(aterminals[0].op & NOTPAT))) {    /* must do normal processing */
  69.         if (AComplexBoolean && (AParse != NULL)) destroy_tree(AParse);    /* so that direct exec invocations don't use AParse by mistake! */
  70. #if    DEBUG
  71.         fprintf(stderr, "preprocess: split_pat = %d, split_term = %d, #terms = %d\n", ret1, ret2, anum_terminals);
  72. #endif    /*DEBUG*/
  73.         /*
  74.         if (ret2 == 1) {
  75.             strcpy(Pattern, aterminals[0].data.leaf.value);
  76.             m = strlen(Pattern);
  77.         }
  78.         */
  79.         m = strlen(Pattern);
  80.         AParse = 0;
  81.         free(multibuf);
  82.         multibuf = NULL;
  83.         multilen = 0;
  84.         goto normal_processing;
  85.     }
  86.  
  87.     /* This is quick processing */
  88.     if (AParse != 0) {    /* successfully converted to ANDPAT/ORPAT */
  89.         PAT_BUFFER = 1;
  90.         /* printf("preprocess(): converted= %d, patterns= %s", AParse, multibuf); */
  91.         /* Now I have to process the delimiter if any */
  92.         if (DELIMITER) {
  93.             /* D_pattern is "<PAT>; ", D_length is 1 + length of string PAT: see agrep.c/'d' */
  94.             preprocess_delimiter(D_pattern+1, D_length - 1, D_pattern, &D_length);
  95.             /* D_pattern is the exact stuff we want to match, D_length is its strlen */
  96.             if ((tc_D_length = quick_tcompress(FREQ_FILE, HASH_FILE, D_pattern, D_length, tc_D_pattern, MaxDelimit*2, TC_EASYSEARCH)) <= 0) {
  97.                 strcpy(tc_D_pattern, D_pattern);
  98.                 tc_D_length = D_length;
  99.             }
  100.             /* printf("mgrep's delim=%s,%d tc_delim=%s,%d\n", D_pattern, D_length, tc_D_pattern, tc_D_length); */
  101.         }
  102.         return 0;
  103.     }
  104.     /* else either unknown character, one simple pattern or none at all */
  105.  
  106. normal_processing:
  107.     for(i=0; i< m; i++) {
  108.         if(Pattern[i] == '\\') i++;
  109.         else if(Pattern[i] == '|' || Pattern[i] == '*') REGEX = ON;
  110.     }
  111.  
  112.     r_pat = (CHAR *) malloc(strlen(Pattern)+2*strlen(D_pattern) + 8);    /* bug-report, From: Chris Dalton <crd@hplb.hpl.hp.com> */
  113.     strcpy(temp, D_pattern);
  114.     d_end = t = strlen(temp);  /* size of D_pattern, including '; ' */
  115.     if (WHOLELINE) { 
  116.         temp[t++] = LANGLE; 
  117.         temp[t++] = NNLINE; 
  118.         temp[t++] = RANGLE;
  119.         temp[t] = '\0';
  120.         strcat(temp, Pattern);
  121.         m = strlen(temp);
  122.         temp[m++] = LANGLE; 
  123.         temp[m++] = '\n'; 
  124.         temp[m++] = RANGLE; 
  125.         temp[m] = '\0';  
  126.     }
  127.     else {
  128.         if (WORDBOUND) { 
  129.             temp[t++] = LANGLE; 
  130.             temp[t++] = WORDB; 
  131.             temp[t++] = RANGLE;
  132.             temp[t] = '\0'; 
  133.         }
  134.         strcat(temp, Pattern);
  135.         m = strlen(temp);
  136.         if (WORDBOUND) { 
  137.             temp[m++] = LANGLE; 
  138.             temp[m++] = WORDB; 
  139.             temp[m++] = RANGLE; 
  140.         }
  141.         temp[m] = '\0';
  142.     }
  143.     /* now temp contains augmented pattern , m it's size */
  144.     D_length = 0;
  145.     for (i=0, j=0; i< d_end-2; i++) {
  146.         switch(temp[i]) 
  147.         {
  148.         case '\\' : 
  149.             i++; 
  150.             Pattern[j++] = temp[i];
  151.             old_D_pat[D_length++] = temp[i];
  152.             break;
  153.         case '<'  : 
  154.             Pattern[j++] = LANGLE;
  155.             break;
  156.         case '>'  : 
  157.             Pattern[j++] = RANGLE;
  158.             break;
  159.         case '^'  : 
  160.             Pattern[j++] = '\n';
  161.             old_D_pat[D_length++] = temp[i];
  162.             break;
  163.         case '$'  : 
  164.             Pattern[j++] = '\n';
  165.             old_D_pat[D_length++] = temp[i];
  166.             break;
  167.         default  :  
  168.             Pattern[j++] = temp[i];
  169.             old_D_pat[D_length++] = temp[i];
  170.             break;
  171.         }
  172.     }
  173.     if(D_length > MAXDELIM) {
  174.         fprintf(stderr, "%s: delimiter pattern too long (has > %d chars)\n", Progname, MAXDELIM);
  175.         free(r_pat);
  176.         if (!EXITONERROR) {
  177.             errno = AGREP_ERROR;
  178.             return -1;
  179.         }
  180.         else exit(2);
  181.     }
  182.  
  183.     Pattern[j++] = ANDPAT;
  184.     old_D_pat[D_length] = '\0';
  185.     strcpy(D_pattern, old_D_pat);
  186.     D_length++;
  187.     /*
  188.       Pattern[j++] = ' ';
  189.     */
  190.     Pattern[j] = '\0';
  191.     rp = 0; 
  192.     if(REGEX) {
  193.         r_pat[rp++] = '.';    /* if REGEX: always append '.' in front */
  194.         r_pat[rp++] = '(';
  195.         Pattern[j++] = NOCARE;
  196.         HEAD = ON;
  197.     }
  198.     for (i=d_end; i < m ; i++)
  199.     {
  200.         switch(temp[i]) 
  201.         {
  202.         case '\\': 
  203.             i++;  
  204.             Pattern[j++] = temp[i]; 
  205.             r_pat[rp++] = 'o';   /* the symbol doesn't matter */
  206.             break;
  207.         case '#':  
  208.             FASTREGEX = ON;
  209.             if(REGEX) {
  210.                 Pattern[j++] = NOCARE;
  211.                 r_pat[rp++] = '.';
  212.                 r_pat[rp++] = '*';
  213.                 break; 
  214.             }
  215.             Pattern[j++] = WILDCD;
  216.             break; 
  217.         case '(':  
  218.             Pattern[j++] = LPARENT; 
  219.             r_pat[rp++] = '(';     
  220.             break;
  221.         case ')':  
  222.             Pattern[j++] = RPARENT; 
  223.             r_pat[rp++] = ')'; 
  224.             break;
  225.         case '[':  
  226.             Pattern[j++] = LRANGE;  
  227.             r_pat[rp++] = '[';
  228.             IN_RANGE = ON;
  229.             break;
  230.         case ']':  
  231.             Pattern[j++] = RRANGE;  
  232.             r_pat[rp++] = ']'; 
  233.             IN_RANGE = OFF;
  234.             break;
  235.         case '<':  
  236.             Pattern[j++] = LANGLE;  
  237.             break;
  238.         case '>':  
  239.             Pattern[j++] = RANGLE;  
  240.             break;
  241.         case '^':  
  242.             if (temp[i-1] == '[') Pattern[j++] = NOTSYM;
  243.             else Pattern[j++] = '\n';
  244.             r_pat[rp++] = '^';
  245.             break;
  246.         case '$':  
  247.             Pattern[j++] = '\n'; 
  248.             r_pat[rp++] = '$';
  249.             break;
  250.         case '.':  
  251.             Pattern[j++] = NOCARE;
  252.             r_pat[rp++] = '.';
  253.             break;
  254.         case '*':  
  255.             Pattern[j++] = STAR; 
  256.             r_pat[rp++] = '*';
  257.             break;
  258.         case '|':  
  259.             Pattern[j++] = ORSYM; 
  260.             r_pat[rp++] = '|';
  261.             break;
  262.         case ',':  
  263.             Pattern[j++] = ORPAT;  
  264.             RE_ERR = ON; 
  265.             break;
  266.         case ';':  
  267.             if(ANDON) RE_ERR = ON; 
  268.             Pattern[j++] = ANDPAT;
  269.             ANDON = ON;
  270.             break;
  271.         case '-':  
  272.             if(IN_RANGE) {
  273.                 Pattern[j++] = HYPHEN; 
  274.                 r_pat[rp++] = '-';
  275.             }
  276.             else { 
  277.                 Pattern[j++] = temp[i];
  278.                 r_pat[rp++] = temp[i];
  279.             }  
  280.             break;
  281.         case NNLINE :
  282.             Pattern[j++] = temp[i];
  283.             r_pat[rp++] = 'N';
  284.             break;
  285.         default:   
  286.             Pattern[j++] = temp[i]; 
  287.             r_pat[rp++] = temp[i];
  288.             break;
  289.         }
  290.     }
  291.     if(REGEX) {           /* append ').' at end of regular expression */
  292.         r_pat[rp++] = ')';
  293.         r_pat[rp++] = '.';
  294.         Pattern[j++] = NOCARE;
  295.         TAIL = ON;
  296.     }
  297.     Pattern[j] = '\0'; 
  298.     m = j;
  299.     r_pat[rp] = '\0'; 
  300.     if(REGEX)
  301.     {  
  302.         if(DELIMITER || WORDBOUND)  {
  303.             fprintf(stderr, "%s: -d or -w option is not supported for this pattern\n", Progname);
  304.             free(r_pat);
  305.             if (!EXITONERROR) {
  306.                 errno = AGREP_ERROR;
  307.                 return -1;
  308.             }
  309.             else exit(2);
  310.         }
  311.         if(RE_ERR) {
  312.             fprintf(stderr, "%s: illegal regular expression\n", Progname);
  313.             free(r_pat);
  314.             if (!EXITONERROR) {
  315.                 errno = AGREP_ERROR;
  316.                 return -1;
  317.             }
  318.             else exit(2);
  319.         }
  320.         while(*Pattern != NOCARE && m-- > 0) Pattern++;  /* poit to . */
  321.         num_pos = init(r_pat, table);
  322.         if(num_pos <= 0) {
  323.             fprintf(stderr, "%s: illegal regular expression\n", Progname);
  324.             free(r_pat);
  325.             if (!EXITONERROR) {
  326.                 errno = AGREP_ERROR;
  327.                 return -1;
  328.             }
  329.             else exit(2);
  330.         }
  331.         if(num_pos > 30) {
  332.             fprintf(stderr, "%s: regular expression too long\n", Progname);
  333.             free(r_pat);
  334.             if (!EXITONERROR) {
  335.                 errno = AGREP_ERROR;
  336.                 return -1;
  337.             }
  338.             else exit(2);
  339.         }
  340.         strcpy(old_pat, Pattern); /* do real change to the Pattern to be returned */
  341.         free(r_pat);
  342.         return 0;
  343.     } /* if regex */
  344.  
  345.     free(r_pat);
  346.     return 0;
  347. }
  348.  
  349.